import re

import pyglet
from pyglet.gl import *
from pyglet.window import key

import camera

tile_images = {0: pyglet.image.load("../data/map/testtile.png"),
               1: pyglet.image.load("../data/map/grasstile.png"),
               2: pyglet.image.load("../data/map/concretetile.png"),
               }
tile_overlay_images = {0: pyglet.image.load("../data/map/grass_overlap_bottom.png"),
                       }
tile_width = 100
tile_height = 50

def isometric_map_coord_to_world_coord(isox, isoy):
    x = (isoy%2)*tile_width/2.0 + isox*tile_width
    y = isoy*tile_height/2.0
    
    return x, y

class MapObject(object):
    def __init__(self, x, y):
        self.position = x, y

class IsometricMapObject(MapObject):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def __get_position(self):
        return isometric_map_coord_to_world_coord(self.__x, self.__y)
    position = property(__get_position)

class IsometricTile(IsometricMapObject):
    def __init__(self, x, y, type, attr):
        """Set up an isometric tile, with map coordinates x, y.
        Since this is an isometric map, the map coordinates are
        not proportional to the coordinates in which they will be
        positioned when drawn. To get this value, the position
        property is provided.
        The tile type is defined by type and specific attributes
        by attr."""

        IsometricMapObject.__init__(self, x, y)
        self.type = type
        self.attr = attr

class Map(object):
    def __init__(self, filename):
        self.parse_map(filename)

    def draw(self, win, cam):
        glPushMatrix()

        for tile in self.tile_layer:
            cam.focus(win.width, win.height)
            x, y = tile.position
            glTranslatef(x, y, 0)
            tile_images[tile.type].blit(0,0)

        #for tile in self.tile_overlay:
        #    cam.focus(win.width, win.height)
        #    x = (tile.y%2)*tile_width/2 + tile.x*tile_width
        #    y = tile.y*tile_height/2
        #    glTranslatef(x, y, 0)
        #    tile_overlay_images[tile.type].blit(0,0)
        #for structure in self.structures:
        #    structure.draw()
        glPopMatrix()

    def parse_map(self, filename):
        f = open(filename)
        cont = f.read()
        f.close()

        map = re.search("(?s)MAP\nVER (.*?)\nNAME (.*?)\nWIDTH (.*?)\nHEIGHT (.*?)\nFOCUS TILE (.*?) (.*?)\n.*?BEGIN TILES\n(.*?)\nEND TILES", cont)
        if map is None:
            raise IOError("Invalid file format")

        ver = float(map.group(1))  # Version of parser
        name = map.group(2)        # Name of the map to display
        width = int(map.group(3))  # Width of map in tiles
        height = int(map.group(4)) # Height of map in tiles
        focus_tile = isometric_map_coord_to_world_coord(int(map.group(5)), 
                                                        int(map.group(6)))
                                   # What tile to focus the camera on
        tile_string = map.group(7) # The tile data
        #structure_string =         # Placable structure data
        #enemy_string =             # The enemy data

        tiles = re.findall("(?s).*?TILE\nTYPE (.*?)\nATTRIBUTES (.*?)\n", tile_string)

        if len(tiles) is not width*height:
            raise IOError("Invalid map size or missing tile data")
        
        # Clear already existing contents
        self.tile_layer = []
    
        for y in xrange(height):
            for x in xrange(width):
                tile = tiles[y * width + x]
                self.tile_layer.append(IsometricTile(x, y, 
                                                     int(tile[0]), 
                                                     int(tile[1])))
                
def test():
    win_width = 1024
    win_height = 786
    
    window = pyglet.window.Window(win_width, win_height)

    map = Map("../data/maps/testmap.map")

    glClearColor(0, 1, 0, 0)
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    cam = camera.Camera((0,0),scale=20)

    @window.event
    def on_draw():
        window.clear()
        cam.focus(window.width, window.height)
        map.draw(window, cam)

    @window.event
    def on_key_press(sym, mod):
        if sym == key.UP:
            cam.y += cam.scale
        if sym == key.DOWN:
            cam.y -= cam.scale
        if sym == key.LEFT:
            cam.x -= cam.scale
        if sym == key.RIGHT:
            cam.x += cam.scale
        if sym == key.MINUS:
            cam.scale *= 2
        if sym == key.PLUS:
            cam.scale /= 2.0
    pyglet.app.run()
    

if __name__ == "__main__":
    test()
    
